package com.self.av;

import android.annotation.SuppressLint;
import android.content.ContentResolver;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.PointF;
import android.icu.text.SimpleDateFormat;
import android.net.Uri;
import android.os.Environment;
import android.os.ParcelFileDescriptor;
import android.provider.OpenableColumns;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import com.google.mediapipe.tasks.components.containers.NormalizedLandmark;

import org.json.JSONArray;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;

public class Utils {

    public static final int[] KEY_IDS = {
            13, 14, 15, 16
    };

    public static void save_local(Context context, Bitmap bitmap) {
        File storageDir = context.getExternalFilesDir(null);
        String timeStamp = null;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
            timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(new Date());
        }
        String fileName = "JPEG_" + timeStamp + ".jpg";
        File imageFile = new File(storageDir, fileName);
        try (FileOutputStream fos = new FileOutputStream(new File(storageDir, fileName))) {
            // 将 Bitmap 压缩为 JPG 格式并保存
            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
            Log.e("@@@@@", "Image saved: " + imageFile.getAbsolutePath());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @SuppressLint("Range")
    public static String getFileName(ContentResolver contentResolver, Uri uri) {
        String result = null;
        if (uri.getScheme().equals("content")) {
            Cursor cursor = contentResolver.query(uri, null, null, null, null);
            try {
                if (cursor != null && cursor.moveToFirst()) {
                    result = cursor.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
                }
            } finally {
                if (cursor != null) {
                    cursor.close();
                }
            }
        }
        if (result == null) {
            result = uri.getPath();
            int cut = result.lastIndexOf('/');
            if (cut != -1) {
                result = result.substring(cut + 1);
            }
        }
        return result;
    }

    // 新增：统计文件行数的工具方法
//    public static int countFileLines(File file) {
//        int lineCount = 0;
//        try (BufferedReader reader = new BufferedReader(new FileReader(file))) {
//            // 逐行读取并计数（忽略空行）
//            while (reader.readLine() != null) {
//                lineCount++;
//            }
//        } catch (IOException e) {
//            Log.e("FileLineCount", "读取文件行数失败", e);
//            lineCount = -1; // 用-1表示读取失败
//        }
//        return lineCount;
//    }
    public static List<List<NormalizedLandmark>> applyFilter(List<List<NormalizedLandmark>> prevLandmarks, List<List<NormalizedLandmark>> newLandmarks) {
        float ALPHA = 0.3f;
        // 定义一个阈值，用于判断新老 landmark 的差距
        float DISTANCE_THRESHOLD = 0.1f;

        if (prevLandmarks.size() == 0) {
            for (List<NormalizedLandmark> personLandmarks : newLandmarks) {
                List<NormalizedLandmark> filteredPersonLandmarks = new ArrayList<>();
                for (NormalizedLandmark landmark : personLandmarks) {
                    filteredPersonLandmarks.add(landmark);
                }
                prevLandmarks.add(filteredPersonLandmarks);
            }
            return newLandmarks;
        }

        List<List<NormalizedLandmark>> filteredLandmarks = new ArrayList<>();
        for (int personIndex = 0; personIndex < newLandmarks.size(); personIndex++) {
            List<NormalizedLandmark> newPersonLandmarks = newLandmarks.get(personIndex);
            List<NormalizedLandmark> prevPersonLandmarks = prevLandmarks.get(personIndex);
            List<NormalizedLandmark> filteredPersonLandmarks = new ArrayList<>();

            for (int landmarkIndex = 0; landmarkIndex < newPersonLandmarks.size(); landmarkIndex++) {
                NormalizedLandmark newLandmark = newPersonLandmarks.get(landmarkIndex);
                NormalizedLandmark prevLandmark = prevPersonLandmarks.get(landmarkIndex);

                // 计算新老 landmark 的欧几里得距离
                float dx = newLandmark.x() - prevLandmark.x();
                float dy = newLandmark.y() - prevLandmark.y();
                float dz = newLandmark.z() - prevLandmark.z();
                float distance = (float) Math.sqrt(dx * dx + dy * dy + dz * dz);

                if (distance > DISTANCE_THRESHOLD) {
                    // 若差距超过阈值，直接使用新的 landmark
                    filteredPersonLandmarks.add(newLandmark);
                } else {
                    // 若差距未超过阈值，进行降噪处理
                    float filteredX = ALPHA * newLandmark.x() + (1 - ALPHA) * prevLandmark.x();
                    float filteredY = ALPHA * newLandmark.y() + (1 - ALPHA) * prevLandmark.y();
                    float filteredZ = ALPHA * newLandmark.z() + (1 - ALPHA) * prevLandmark.z();

                    NormalizedLandmark filteredLandmark = NormalizedLandmark.create(filteredX, filteredY, filteredZ);
                    filteredPersonLandmarks.add(filteredLandmark);
                }
            }
            filteredLandmarks.add(filteredPersonLandmarks);
        }

        prevLandmarks = filteredLandmarks;
        return filteredLandmarks;
    }

    public static String calculateMD5FromUri(Context context, Uri uri) {
        if (context == null || uri == null) {
            return null;
        }

        MessageDigest messageDigest = null;
        ParcelFileDescriptor parcelFileDescriptor = null;
        FileInputStream fis = null;

        try {
            // 获取MD5消息摘要实例
            messageDigest = MessageDigest.getInstance("MD5");

            // 通过URI获取文件描述符
            parcelFileDescriptor = context.getContentResolver().openFileDescriptor(uri, "r");
            if (parcelFileDescriptor == null) {
                return null;
            }

            // 获取文件输入流
            fis = new FileInputStream(parcelFileDescriptor.getFileDescriptor());
            FileChannel channel = fis.getChannel();

            // 1MB缓冲区
            ByteBuffer byteBuffer = ByteBuffer.allocate(1024 * 1024);

            int bytesRead;
            while ((bytesRead = channel.read(byteBuffer)) != -1) {
                if (bytesRead > 0) {
                    byteBuffer.flip();
                    messageDigest.update(byteBuffer);
                    byteBuffer.clear();
                }
            }

            // 计算并转换为十六进制字符串
            byte[] md5Bytes = messageDigest.digest();
            return bytesToHex(md5Bytes);

        } catch (NoSuchAlgorithmException | IOException e) {
            e.printStackTrace();
        } finally {
            // 关闭资源
            if (fis != null) {
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (parcelFileDescriptor != null) {
                try {
                    parcelFileDescriptor.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return null;
    }

    private static String bytesToHex(byte[] bytes) {
        if (bytes == null || bytes.length == 0) {
            return null;
        }

        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            String hex = Integer.toHexString(0xFF & b);
            if (hex.length() == 1) {
                sb.append('0');
            }
            sb.append(hex);
        }
        return sb.toString();
    }


    public static HashMap<Integer, List<NormalizedLandmark>> loadPreprocessData(Context context, Uri videoUri) {
        // 清空原有数据，避免重复加载
        HashMap<Integer, List<NormalizedLandmark>> preprocessData = new HashMap<>();

        // 获取视频MD5和结果文件路径（与PreprocessActivity保持一致）
        String videoMd5 = calculateMD5FromUri(context.getApplicationContext(), videoUri);
        if (videoMd5 == null) {
            Log.e("LoadPreprocessData", "视频MD5计算失败");
            return preprocessData;
        }

        File saveDir = new File(context.getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS), "av_pose_results");
        File resultFile = new File(saveDir, videoMd5 + ".json");

        // 文件不存在则直接返回
        if (!resultFile.exists()) {
            Log.d("LoadPreprocessData", "预处理结果文件不存在: " + resultFile.getAbsolutePath());
            return preprocessData;
        }

        // 逐行读取JSON文件
        try (BufferedReader reader = new BufferedReader(new FileReader(resultFile))) {
            String line;
            while ((line = reader.readLine()) != null) {
                // 跳过空行
                if (line.trim().isEmpty()) continue;

                // 解析单帧JSON数据
                JSONObject frameJson = new JSONObject(line);
                int frameIndex = frameJson.getInt("frameIndex"); // 提取帧数作为key

                // 提取 landmarks 数据（以第一个姿态的第15个关键点为例，可根据需求修改）
                JSONArray landmarksArray = frameJson.getJSONArray("landmarks");
                if (landmarksArray.length() > 0) {
                    JSONArray poseArray = landmarksArray.getJSONArray(0); // 取第一个姿态
                    List<NormalizedLandmark> pointFList = new ArrayList<>();
                    if (poseArray.length() > 15) { // 确保关键点索引存在（15对应右手腕，可调整）
                        for (int i = 0; i < poseArray.length(); i++) {
                            JSONObject landmarkJson = poseArray.getJSONObject(i);
                            float x = (float) landmarkJson.getDouble("x");
                            float y = (float) landmarkJson.getDouble("y");
                            float z = (float) landmarkJson.getDouble("z");
                            pointFList.add(NormalizedLandmark.create(x, y, z));
                        }
                    }
                    preprocessData.put(frameIndex, pointFList); // 存入HashMap
                }
            }
            return preprocessData;
        } catch (Exception e) {
            Log.e("LoadPreprocessData", "文件读取失败", e);
        }
        return new HashMap<>();
    }

    public static double calculateAngle(PointF a, PointF b, PointF c) {
        // 计算向量ba和bc
        float baX = a.x - b.x;
        float baY = a.y - b.y;
        float bcX = c.x - b.x;
        float bcY = c.y - b.y;

        // 计算点积
        float dotProduct = baX * bcX + baY * bcY;

        // 计算模长
        float magnitudeBA = (float) Math.sqrt(baX * baX + baY * baY);
        float magnitudeBC = (float) Math.sqrt(bcX * bcX + bcY * bcY);

        // 防止除以零
        if (magnitudeBA == 0 || magnitudeBC == 0) {
            return 0;
        }

        // 计算余弦值
        float cosine = dotProduct / (magnitudeBA * magnitudeBC);

        // 防止数值误差导致cosine超出[-1, 1]范围
        cosine = Math.max(-1f, Math.min(1f, cosine));

        // 计算弧度并转换为角度
        return Math.toDegrees(Math.acos(cosine));
    }

}
